/* Author: alex

*/

Namespace("sketch.util");

function Inherits(subClass, superClass) {
    subClass.prototype = new superClass();
    subClass.constructor = subClass;
    subClass.baseConstructor = superClass;
    subClass.superClass = superClass.prototype;
};


function EventHandler(that, method) {
    return function () {
        method.apply(that, arguments);
    }
}

function each(array, callback){
    for (var i = 0, j = array.length; i < j; ++i) {
        var result = callback(array[i], i);
        if (result === false){
            return;
        }
    }
}

sketch.util.min = function(array, accessor){
    var result = null;
    each(array, function(element){
        var value = accessor(element);
        if (result === null || value < result){
            result = value;
        }
    });
    return result;
};

sketch.util.max = function(array, accessor){
    var result = null;
    each(array, function(element){
        var value = accessor(element);
        if (result === null || value > result){
            result = value;
        }
    });
    return result;
};

sketch.util.elementWithMax = function(array, accessor){
    var result = null;
    var maxValue = null;
    each(array, function(element){
        var value = accessor(element);
        if (maxValue === null || value > maxValue){
            maxValue = value;
            result = element;
        }
    });
    return result;
};
sketch.util.elementWithMin = function(array, accessor){
    var result = null;
    var minValue = null;
    each(array, function(element){
        var value = accessor(element);
        if (minValue === null || value < minValue){
            minValue = value;
            result = element;
        }
    });
    return result;
};

sketch.util.sum = function(array, accessor){
    var result = 0;
    each(array, function(element){
        result += accessor(element);
    });
    return result;
};

function toArray(array, callback){
    var result = [];
    for (var i = 0, j = array.length; i < j; ++i) {
        result.push(callback(array[i]));
    }
    return result;
}

function areSameArrays(array1, array2){
    if (!array1 || !array2){
        return false;
    }
    if (array1.length !== array2.length){
        return false;
    }
    for (var i = 0, j = array1.length; i < j; ++i) {
        if(array1[i] !== array2[i]){
            return false;
        }
    }
    return true;
}

if (!window.requestAnimationFrame) {

    window.requestAnimationFrame = (function () {

        return window.webkitRequestAnimationFrame ||
            window.mozRequestAnimationFrame ||
            window.oRequestAnimationFrame ||
            window.msRequestAnimationFrame ||
            function ( /* function FrameRequestCallback */callback, /* DOMElement Element */element) {

                window.setTimeout(callback, 1000 / 30);

            };

    })();
};

function argumentNames(func) {
    var names = func.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1]
      .replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '')
      .replace(/\s+/g, '').split(',');
    return names.length == 1 && !names[0] ? [] : names;
}

function klass(Parent, props) {
    var Child, F, i;

    // new constructor
    Child = function () {        
        Child.prototype._constructor.apply(this, arguments);
    };

    // inherit
    Parent = Parent || Object;
    F = function () { };
    F.prototype = Parent.prototype;
    Child.prototype = new F();
    Child.Super = Parent.prototype;
    Child.SuperConstructor = Parent.constructor;
    Child.constructor = Child;
    Child.prototype.Klass = Child;
    Child.prototype.SuperKlass = Parent.prototype;
    
    // add implementation methods
    for (i in props) {
        if (props.hasOwnProperty(i)) {
            var member = props[i];

            if (typeof member === "function"){
                var args = argumentNames(member);
                if (args.length !== 0 && args[0] === "$super") {
                    (function(){
                        var original = member;
                        var name = i;
                        member = function() {
                            var that = this;
                            var superFunc = function(){
                                return Parent.prototype[name].apply(that, arguments);
                            };
                            var newArgs = [];
                            newArgs.push(superFunc);
                            for (var j = 0, k = arguments.length; j < k; ++j) {
                                newArgs.push(arguments[j]);
                            }
                            return original.apply(this, newArgs);
                        };
                    })();
                }

            }

            Child.prototype[i] = member;
        }
    }

    var ownConstructor = null;
    if (Child.prototype.hasOwnProperty("_constructor")) {
        ownConstructor = Child.prototype._constructor;
    }

    Child.prototype._constructor = function () {
        var callSuper = true;
        if (Child.prototype.hasOwnProperty("_callSuper")) {
            callSuper = Child.prototype._callSuper;
        }

        if (callSuper && Child.Super && Child.Super.hasOwnProperty("_constructor")) {
            Child.Super._constructor.apply(this, arguments);
        }

        if (ownConstructor != null) {
            ownConstructor.apply(this, arguments);
        }
    }

    return Child;
}
























